
namespace PaulRz.Util.Patterns
{
    /// <summary>
    /// Singleton pattern abstract class
    /// The implementation of Instance is not thread-safe at the first call
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class Singleton<T> where T : new()
    {
        protected Singleton()
        {
            
        }
        
        protected static T _self = default(T);
        
        /// <summary>
        /// Returns the instance of T
        /// </summary>
        public static T Instance
        {
            get
            {
                if (_self == null)
                {
                    _self = new T();
                }
                return _self;
            }
        }
        
    }
    
    /// <summary>
    /// Thread-safe singleton implementation
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class SyncSingleton<T> : Singleton<T> where T : new()
    {
        protected SyncSingleton()
        {
            
        }
        
        protected static object SyncRoot = new object();

        /// <summary>
        /// Return the instance of T
        /// </summary>
        public new static T Instance
        {
            get
            {
                if (_self == null)
                {
                    // double-locking technics fortunately work in CLR 2.0
                    lock (SyncRoot)
                    {
                        if (_self==null)
                            _self = new T();
                    }
                }
                return _self;
            }
        }
    }
}
